package service

import (
	"admin-nexus-backend/internal/dto"
	"admin-nexus-backend/internal/model"
	"errors"

	"gorm.io/gorm"
)

type RoleService struct {
	db *gorm.DB
}

func NewRoleService(db *gorm.DB) *RoleService {
	return &RoleService{db: db}
}

// GetRoleList 获取角色列表
func (s *RoleService) GetRoleList(params *dto.RoleQueryParams) (*dto.PageResult, error) {
	var roles []model.Role
	var total int64

	query := s.db.Model(&model.Role{})

	// 条件查询
	if params.Name != "" {
		query = query.Where("name LIKE ?", "%"+params.Name+"%")
	}
	if params.Code != "" {
		query = query.Where("code LIKE ?", "%"+params.Code+"%")
	}
	if params.Status != nil {
		query = query.Where("status = ?", *params.Status)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, err
	}

	// 分页查询
	offset := (params.Page - 1) * params.PageSize
	if err := query.Offset(offset).Limit(params.PageSize).Order("sort ASC, id DESC").Find(&roles).Error; err != nil {
		return nil, err
	}

	return &dto.PageResult{
		List:     roles,
		Total:    total,
		Page:     params.Page,
		PageSize: params.PageSize,
	}, nil
}

// GetAllRoles 获取所有角色
func (s *RoleService) GetAllRoles() ([]model.Role, error) {
	var roles []model.Role
	if err := s.db.Where("status = 1").Order("sort ASC, id DESC").Find(&roles).Error; err != nil {
		return nil, err
	}
	return roles, nil
}

// GetRoleByID 根据 ID 获取角色
func (s *RoleService) GetRoleByID(id uint) (*model.Role, error) {
	var role model.Role
	if err := s.db.Preload("Resources").Preload("DataPermission").First(&role, id).Error; err != nil {
		return nil, err
	}
	return &role, nil
}

// CreateRole 创建角色
func (s *RoleService) CreateRole(req *dto.RoleCreateRequest) error {
	// 检查角色名称是否存在
	var count int64
	if err := s.db.Model(&model.Role{}).Where("name = ?", req.Name).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("角色名称已存在")
	}

	// 检查角色编码是否存在
	if err := s.db.Model(&model.Role{}).Where("code = ?", req.Code).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("角色编码已存在")
	}

	// 创建角色
	role := &model.Role{
		Name:   req.Name,
		Code:   req.Code,
		Sort:   req.Sort,
		Status: req.Status,
		Remark: req.Remark,
	}

	// 开启事务
	return s.db.Transaction(func(tx *gorm.DB) error {
		// 创建角色
		if err := tx.Create(role).Error; err != nil {
			return err
		}

		// 分配资源
		// 复制用户提供的资源ID列表
		resourceIDs := make([]uint, len(req.ResourceIDs))
		copy(resourceIDs, req.ResourceIDs)

		// 查询个人资料页面资源
		var personalResource model.Resource
		if err := tx.Where("code = ? AND type = ?", "personal", 1).First(&personalResource).Error; err == nil {
			// 检查是否已经包含个人资料页面
			contains := false
			for _, id := range resourceIDs {
				if id == personalResource.ID {
					contains = true
					break
				}
			}
			// 如果不包含，则添加个人资料页面资源
			if !contains {
				resourceIDs = append(resourceIDs, personalResource.ID)
			}
		}

		// 创建资源关联
		if len(resourceIDs) > 0 {
			var roleResources []model.RoleResource
			for _, resourceID := range resourceIDs {
				roleResources = append(roleResources, model.RoleResource{
					RoleID:     role.ID,
					ResourceID: resourceID,
				})
			}
			if err := tx.Create(&roleResources).Error; err != nil {
				return err
			}
		}

		return nil
	})
}

// UpdateRole 更新角色
func (s *RoleService) UpdateRole(id uint, req *dto.RoleUpdateRequest) error {
	// 检查角色是否存在
	var role model.Role
	if err := s.db.First(&role, id).Error; err != nil {
		return err
	}

	// 检查角色名称是否被其他角色使用
	if req.Name != "" && req.Name != role.Name {
		var count int64
		if err := s.db.Model(&model.Role{}).Where("name = ? AND id != ?", req.Name, id).Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return errors.New("角色名称已被使用")
		}
	}

	// 检查角色编码是否被其他角色使用
	if req.Code != "" && req.Code != role.Code {
		var count int64
		if err := s.db.Model(&model.Role{}).Where("code = ? AND id != ?", req.Code, id).Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return errors.New("角色编码已被使用")
		}
	}

	// 开启事务
	return s.db.Transaction(func(tx *gorm.DB) error {
		// 更新角色信息
		updates := map[string]interface{}{
			"name":   req.Name,
			"code":   req.Code,
			"sort":   req.Sort,
			"status": req.Status,
			"remark": req.Remark,
		}
		if err := tx.Model(&role).Updates(updates).Error; err != nil {
			return err
		}

		// 更新资源
		if req.ResourceIDs != nil {
			// 删除旧的资源关联
			if err := tx.Where("role_id = ?", id).Delete(&model.RoleResource{}).Error; err != nil {
				return err
			}

			// 添加新的资源关联
			if len(req.ResourceIDs) > 0 {
				var roleResources []model.RoleResource
				for _, resourceID := range req.ResourceIDs {
					roleResources = append(roleResources, model.RoleResource{
						RoleID:     id,
						ResourceID: resourceID,
					})
				}
				if err := tx.Create(&roleResources).Error; err != nil {
					return err
				}
			}
		}

		return nil
	})
}

// DeleteRole 删除角色
func (s *RoleService) DeleteRole(id uint) error {
	// 检查角色是否被用户使用
	var count int64
	if err := s.db.Model(&model.UserRole{}).Where("role_id = ?", id).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("该角色已被用户使用，无法删除")
	}

	return s.db.Transaction(func(tx *gorm.DB) error {
		// 删除角色资源关联
		if err := tx.Where("role_id = ?", id).Delete(&model.RoleResource{}).Error; err != nil {
			return err
		}

		// 删除角色（软删除）
		if err := tx.Delete(&model.Role{}, id).Error; err != nil {
			return err
		}

		return nil
	})
}

// AssignResources 分配资源
func (s *RoleService) AssignResources(roleID uint, req *dto.RoleResourceRequest) error {
	// 检查角色是否存在
	var role model.Role
	if err := s.db.First(&role, roleID).Error; err != nil {
		return err
	}

	return s.db.Transaction(func(tx *gorm.DB) error {
		// 删除旧的资源关联
		if err := tx.Where("role_id = ?", roleID).Delete(&model.RoleResource{}).Error; err != nil {
			return err
		}

		// 添加新的资源关联
		if len(req.ResourceIDs) > 0 {
			var roleResources []model.RoleResource
			for _, resourceID := range req.ResourceIDs {
				roleResources = append(roleResources, model.RoleResource{
					RoleID:     roleID,
					ResourceID: resourceID,
				})
			}
			if err := tx.Create(&roleResources).Error; err != nil {
				return err
			}
		}

		return nil
	})
}

// GetRoleResources 获取角色的资源 ID 列表
func (s *RoleService) GetRoleResources(roleID uint) ([]uint, error) {
	var resourceIDs []uint
	err := s.db.Model(&model.RoleResource{}).
		Where("role_id = ?", roleID).
		Pluck("resource_id", &resourceIDs).Error
	return resourceIDs, err
}

// GetRoleDataPermission 获取角色数据权限
func (s *RoleService) GetRoleDataPermission(roleID uint) (*model.RoleDataPermission, error) {
	var dataPermission model.RoleDataPermission
	if err := s.db.Where("role_id = ?", roleID).First(&dataPermission).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			// 如果没有数据权限记录，返回默认值
			return &model.RoleDataPermission{
				RoleID:    roleID,
				DataScope: 0, // 默认全部数据权限
				OrgIDs:    "",
			}, nil
		}
		return nil, err
	}
	return &dataPermission, nil
}

// UpdateRoleDataPermission 更新角色数据权限
func (s *RoleService) UpdateRoleDataPermission(roleID uint, dataPermission *model.RoleDataPermission) error {
	// 检查角色是否存在
	var role model.Role
	if err := s.db.First(&role, roleID).Error; err != nil {
		return errors.New("角色不存在")
	}

	// 设置角色ID
	dataPermission.RoleID = roleID

	// 检查是否已存在数据权限记录
	var existing model.RoleDataPermission
	err := s.db.Where("role_id = ?", roleID).First(&existing).Error

	if err == gorm.ErrRecordNotFound {
		// 不存在，创建新记录
		return s.db.Create(dataPermission).Error
	} else if err != nil {
		// 其他错误
		return err
	}

	// 存在，更新记录
	return s.db.Model(&existing).Updates(map[string]interface{}{
		"data_scope": dataPermission.DataScope,
		"org_ids":    dataPermission.OrgIDs,
	}).Error
}
